package com.ghxxzx.daglcustom.controller.model;

import com.ghxxzx.daglcustom.utils.CreatedTools;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
public class ActivitiModelController {

	@Autowired
	private ProcessEngine processEngine;
	@Autowired
	private ObjectMapper objectMapper;
	@Autowired
	private TaskService taskService;
	@Autowired
	private IdentityService identityService;

	/**
	 * 新建一个空模型
	 */
	@RequestMapping("/create")
	public void newModel(HttpServletRequest request, HttpServletResponse response) throws IOException {
		RepositoryService repositoryService = processEngine.getRepositoryService();
		// 初始化一个空模型
		Model model = repositoryService.newModel();

		// 设置一些默认信息
		String name = "";
		String description = "";
		int revision = 1;
		String key = "m_" + CreatedTools.getCreated();
		// 设置子系统
		model.setTenantId("子系统1");

		ObjectNode modelNode = objectMapper.createObjectNode();
		modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
		modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
		modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);

		model.setName(name);
		model.setKey(key);
		model.setMetaInfo(modelNode.toString());

		repositoryService.saveModel(model);
		String id = model.getId();

		// 完善ModelEditorSource
		ObjectNode editorNode = objectMapper.createObjectNode();
		editorNode.put("id", "canvas");
		editorNode.put("resourceId", "canvas");
		ObjectNode stencilSetNode = objectMapper.createObjectNode();
		stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
		editorNode.put("stencilset", stencilSetNode);
		repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8"));
		response.sendRedirect(request.getContextPath() + "/modeler.html?modelId=" + id);
	}

	/**
	 * 获取所有模型
	 */
	@RequestMapping("/modelList")
	@ResponseBody
	public Object modelList(String name) {
		if (name == null) {
			name = "";
		}
		RepositoryService repositoryService = processEngine.getRepositoryService();
		return repositoryService.createModelQuery().modelNameLike("%" + name + "%").modelTenantId("子系统1").list();
	}
	
	@RequestMapping("/modelListPage")
	@ResponseBody
	public Object modelListPage(String name,int page, int limit) {
		if (name == null) {
			name = "";
		}
		RepositoryService repositoryService = processEngine.getRepositoryService();
		int totalCount = (int) repositoryService.createModelQuery().modelNameLike("%" + name + "%").modelTenantId("子系统1").count();
		List<Model> list = repositoryService.createModelQuery().modelNameLike("%" + name + "%").modelTenantId("子系统1").listPage((page - 1) * limit, page * limit);
		Map<String, Object> map = new HashMap<>();
		map.put("list", list);
		map.put("page", page);
		map.put("limit", limit);
		map.put("totalRow", totalCount);
		return map;
	}

	/**
	 * 删除工作流模型
	 */
	@RequestMapping("/deleteModel")
	@ResponseBody
	public Object deleteModel(String modelId) {
		RepositoryService repositoryService = processEngine.getRepositoryService();
		repositoryService.deleteModel(modelId);
		return "SUCCESS";
	}

	/**
	 * 发布模型为流程定义
	 */
	@RequestMapping("/deploy")
	@ResponseBody
	public Object deploy(String modelId) throws Exception {

		// 获取模型
		RepositoryService repositoryService = processEngine.getRepositoryService();
		Model modelData = repositoryService.getModel(modelId);
		byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());

		if (bytes == null) {
			return "模型数据为空，请先设计流程并成功保存，再进行发布。";
		}

		JsonNode modelNode = new ObjectMapper().readTree(bytes);
		BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
		model.setTargetNamespace(modelData.getCategory());

		if (model.getProcesses().size() == 0) {
			return "数据模型不符要求，请至少设计一条主线流程。";
		}
		byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);

		// 发布流程
		String processName = modelData.getName() + ".bpmn20.xml";
		Deployment deployment = repositoryService.createDeployment().name(modelData.getName())
				.category(modelData.getCategory()).addString(processName, new String(bpmnBytes, "UTF-8")).deploy();
		modelData.setDeploymentId(deployment.getId());
		repositoryService.saveModel(modelData);

		return "SUCCESS";
	}

	/**
	 * 启动流程
	 */
	@RequestMapping("/start")
	@ResponseBody
	public Object startProcess(String keyName) {
		// 在流程启动之前设置发起人
		identityService.setAuthenticatedUserId("设置流程发起人为 当前登陆用户");
		// 启动流程
		ProcessInstance process = processEngine.getRuntimeService().startProcessInstanceByKey(keyName);

		// 用于开启第一个 task任务
		Task task = processEngine.getTaskService().createTaskQuery().processInstanceId(process.getId()).singleResult();
		task.setAssignee("请设置为您系统的当前登陆用户");
		taskService.saveTask(task);

		return process.getId() + " : " + process.getProcessDefinitionId();
	}

	/**
	 * 提交任务
	 */
	@RequestMapping("/run")
	@ResponseBody
	public Object run(String processInstanceId) {
		Task task = processEngine.getTaskService().createTaskQuery().processInstanceId(processInstanceId)
				.singleResult();
		// 设置扩展json属性
		task.getDescription();

		System.err.println("task {} find " + task.getId());
		processEngine.getTaskService().complete(task.getId());
		return "SUCCESS";
	}

}
